// Polyfills for NodeList.prototype.forEach
if (NodeList.prototype.forEach === undefined) {
  NodeList.prototype.forEach = Array.prototype.forEach;
}

// Polyfill for Element.prototype.closest
if (!Element.prototype.closest) {
  Element.prototype.closest = function(selector) {
    var element = this;
    while (element) {
      if (element.matches(selector)) {
        return element;
      }
      element = element.parentElement;
    }
    return null;
  };
}

// Polyfill for Element.prototype.matches
if (!Element.prototype.matches) {
  Element.prototype.matches = 
    Element.prototype.msMatchesSelector || 
    Element.prototype.webkitMatchesSelector || 
    function(selector) {
      var matches = (this.document || this.ownerDocument).querySelectorAll(selector),
          i = matches.length;
      while (--i >= 0 && matches.item(i) !== this) {}
      return i > -1;            
  };
}

// Polyfill for Element.classList
if (!("classList" in document.documentElement)) {
  Object.defineProperty(HTMLElement.prototype, 'classList', {
    get: function() {
      var self = this;
      function update(fn) {
        return function(value) {
          var classes = self.className.split(/\s+/),
              index = classes.indexOf(value);
          fn(classes, index, value);
          self.className = classes.join(" ");
        }
      }

      return {
        add: update(function(classes, index, value) {
          if (index === -1) classes.push(value);
        }),

        remove: update(function(classes, index) {
          if (index !== -1) classes.splice(index, 1);
        }),

        toggle: update(function(classes, index, value) {
          if (index !== -1)
            classes.splice(index, 1);
          else
            classes.push(value);
        }),

        contains: function(value) {
          return self.className.split(/\s+/).indexOf(value) !== -1;
        }
      };
    }
  });
}
